package com.n4v1.pko.client.model;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;

import org.newdawn.slick.Animation;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.util.Log;

import com.n4v1.pko.client.model.actor.Character;
import com.n4v1.pko.client.model.map.Map;
import com.n4v1.pko.client.model.map.StandardMap;
import com.n4v1.pko.client.network.clientpackets.MovingPacket;

public class PkoWorld extends BasicGame implements Runnable {
	private static final int CHAR_SIZE = 32;
	private static final int TILE_SIZE = 16;
	private static final float MOVE_SPEED = 0.003f;
	
	private Socket socket;
	private PrintWriter out;
	
	private float playerX = 20;
	private float playerY = 22;
	
	private int widthInTiles;
	private int heightInTiles;
	
	private int topOffsetInTiles;
	private int leftOffsetInTiles;
	
	private Map map;
	private Character character;
	
	public PkoWorld(Socket socket) {
		super("PKO");
		this.socket = socket;
		try {
			out = new PrintWriter(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void init(GameContainer container) throws SlickException {
		SpriteSheet sheet = new SpriteSheet("testdata/scroller/sprites.png",32,32);
		map = new StandardMap("data/maps/start_zone/start_zone.tmx");
		character = new Character("demo", 20.0f, 22.0f);
		widthInTiles = container.getWidth() / TILE_SIZE;
		heightInTiles = container.getHeight() / TILE_SIZE;
		topOffsetInTiles = heightInTiles / 2;
		leftOffsetInTiles = widthInTiles / 2;
//		playerRect = new Rectangle(playerX, playerY, CHAR_SIZE, CHAR_SIZE);
	}

	public void update(GameContainer container, int delta) throws SlickException {
		Input input = container.getInput();
		
//		if (container.getInput().isKeyDown(Input.KEY_LEFT)) {
//			if (tryMove(-delta * MOVE_SPEED, 0)) {
//				player.update(delta);
//			}
//		}
//		if (container.getInput().isKeyDown(Input.KEY_RIGHT)) {
//			if (tryMove(delta * MOVE_SPEED, 0)) {
//				player.update(delta);
//			}
//		}
//		if (container.getInput().isKeyDown(Input.KEY_UP)) {
//			if (tryMove(0, -delta * MOVE_SPEED)) {
//				player.update(delta);
//			}
//		}
//		if (container.getInput().isKeyDown(Input.KEY_DOWN)) {
//			if (tryMove(0, delta * MOVE_SPEED)) {
//				player.update(delta);
//			}
//		}
		
		if(!character.isMoving()) {
			if(input.isKeyDown(Input.KEY_DOWN) && character.getDirection() != 0) {
				character.goDown();
				MovingPacket move = new MovingPacket(out, character.getDirection(), "start");
				move.send();
			}
			if(input.isKeyDown(Input.KEY_LEFT) && character.getDirection() != 1) {
				character.goLeft();
				MovingPacket move = new MovingPacket(out, character.getDirection(), "start");
				move.send();
			}
			if(input.isKeyDown(Input.KEY_RIGHT) && character.getDirection() != 2) {
				character.goRight();
				MovingPacket move = new MovingPacket(out, character.getDirection(), "start");
				move.send();
			}
			if(input.isKeyDown(Input.KEY_UP) && character.getDirection() != 3) {
				character.goUp();
				MovingPacket move = new MovingPacket(out, character.getDirection(), "start");
				move.send();
			}
		}
	}
	
	private boolean tryMove(float x, float y) {
//		float newx = playerX + x;
//		float newy = playerY + y;
//		
//		playerRect.setX(newx);
//		playerRect.setY(newy);
//		
//		if (map.isBlocked(playerRect)) {
//			playerRect.setY(playerY);
//			if (map.isBlocked(playerRect)) {
//				playerRect.setX(playerX);
//				playerRect.setY(newy);
//				if (map.isBlocked(playerRect)) {
//					return false;
//				} else {
//					playerY = newy;
//					return true;
//				}
//			} else {
//				playerX = newx;
//				return true;
//			}
//		} else {
//			playerX = newx;
//			playerY = newy;
//			return true;
//		}
		return true;
	}
	
	public void render(GameContainer container, Graphics g) throws SlickException {
		int playerTileX = (int) playerX;
		int playerTileY = (int) playerY;
		
		int playerTileOffsetX = (int) ((playerTileX - playerX) * TILE_SIZE);
		int playerTileOffsetY = (int) ((playerTileY - playerY) * TILE_SIZE);
		
		map.renderLayer(playerTileOffsetX - (CHAR_SIZE / 2), playerTileOffsetY - (CHAR_SIZE / 2), 
				   playerTileX - leftOffsetInTiles - 1, 
				   playerTileY - topOffsetInTiles - 1,
				   widthInTiles + 3, heightInTiles + 3, 
				   "surface");
		
		map.renderLayer(playerTileOffsetX - (CHAR_SIZE / 2), playerTileOffsetY - (CHAR_SIZE / 2), 
				   playerTileX - leftOffsetInTiles - 1, 
				   playerTileY - topOffsetInTiles - 1,
				   widthInTiles + 3, heightInTiles + 3, 
				   "below");
		
		g.translate(container.getWidth()/2 - (int) (playerX * 32), container.getHeight()/2 - (int) (playerY * 32));
		character.draw(playerX, playerY);
		g.resetTransform();
		
		map.renderLayer(playerTileOffsetX - (CHAR_SIZE / 2), playerTileOffsetY - (CHAR_SIZE / 2), 
				   playerTileX - leftOffsetInTiles - 1, 
				   playerTileY - topOffsetInTiles - 1,
				   widthInTiles + 3, heightInTiles + 3, 
				   "above");
	}
	
	@Override
	public void run() {
		try {
			AppGameContainer container = new AppGameContainer(new PkoWorld(this.socket), 1440, 810, false);
			container.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void keyReleased(int key, char c) {
		if(key == Input.KEY_DOWN
				|| key == Input.KEY_UP
				|| key == Input.KEY_LEFT
				|| key == Input.KEY_RIGHT) {
			character.stopMoving();
			MovingPacket move = new MovingPacket(out, character.getDirection(), "stop");
			move.send();
		}
	}
}

